package com.yang.qqservice.service;

import com.yang.common.Message;
import com.yang.common.MessageType;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description: 该类是和某个客户端保持通信
 * @Author: YANG QIANG
 * @Time: 2022-12-20 21:28
 */
public class ServerConnectClientThread extends Thread{
    // 用来读写数据
    private Socket socket;
    // 当前和哪一个客户端通信
    private String userId;

    public Socket getSocket() {
        return socket;
    }

    public ServerConnectClientThread(Socket socket, String userId) {
        this.socket = socket;
        this.userId = userId;
    }

    /**
     * 用于和客户端通信, 接收和发送数据
     */
    @Override
    public void run() {
       while (true){
           try {
               System.out.println("服务端和客户端[" +userId+ "]保持通信, 读取和发送数据..");

               // 读取数据
               ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
               Message message = (Message) ois.readObject();

               // 判断用户的消息类型
               String messageType = message.getMessageType();

               // 用户获取在线用户列表
               if (MessageType.MESSAGE_GET_ONLINE_FRIEND.equals(messageType)){
                   System.out.println("用户[" + message.getSender() + "] 请求获取在线用户列表");

                   String onlineUsers = ManageClientThread.getOnlineUsers();
                   // 发送给客户端的用户
                   Message message1 = new Message();
                   message1.setMessageType(MessageType.MESSAGE_RET_ONLINE_FRIEND);
                   message1.setContent(onlineUsers);
                   message1.setGetter(message.getSender());

                   // 写入到数据通道
                   ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                   oos.writeObject(message1);
               }

               // 处理客户端退出系统的消息
               if (MessageType.MESSAGE_CLIENT_EXIT.equals(messageType)){
                   System.out.println(message.getSender() + "退出系统...");
                   // 从线程集合中剔除这个突出系统的客户端
                   ManageClientThread.remove(message.getSender());
                   // 关闭连接
                   socket.close();
                   // 退出循环
                   break;
               }

               // 处理客户端的私聊信息
               if (MessageType.MESSAGE_C0MM_MES.equals(messageType)){
                   try {
                       // 判断私聊信息发送的对象是否在线, 不在线就离线存储
                       ConcurrentHashMap<String, ServerConnectClientThread> hm = ManageClientThread.getHm();
                       boolean containsKey = hm.containsKey(message.getGetter());

                       if (containsKey){
                           // 根据message获取需要发送给的userId的对应的线程
                           ServerConnectClientThread serverConnectClientThread = ManageClientThread.getServerConnectClientThread(message.getGetter());
                           // 发送给接收人
                           ObjectOutputStream oos = new ObjectOutputStream(serverConnectClientThread.getSocket().getOutputStream());
                           oos.writeObject(message);
                       }else {
                           // 离线- 保存信息
                           ManageClientThread.addOffLineHm(message.getGetter(), message);
                       }

                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }

               // 处理客户端的群发消息
               if (MessageType.MESSAGE_C0MM_MES_TO_ALL.equals(messageType)){
                   try {
                       // 遍历所有的线程, 排除发送者
                       ConcurrentHashMap<String, ServerConnectClientThread> hm = ManageClientThread.getHm();
                       Iterator<String> iterator = hm.keySet().iterator();
                       while (iterator.hasNext()){
                           String userId = iterator.next();
                           if (!userId.equals(message.getSender())){
                               ServerConnectClientThread serverConnectClientThread = hm.get(userId);
                               // 发送给接收人
                               ObjectOutputStream oos = new ObjectOutputStream(serverConnectClientThread.getSocket().getOutputStream());
                               oos.writeObject(message);
                           }

                       }
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }

               // 处理客户端的文件消息
               if (MessageType.MESSAGE_FILE_MES.equals(messageType)){

                   // 根据getter获取到对应需要转发的用户, 然后进行转发.
                   ServerConnectClientThread clientThread = ManageClientThread.getServerConnectClientThread(message.getGetter());
                   OutputStream outputStream = clientThread.getSocket().getOutputStream();
                   ObjectOutputStream oos = new ObjectOutputStream(outputStream);
                   oos.writeObject(message);

               }

           } catch (Exception e) {
               e.printStackTrace();
           }


       }
    }
}
